package routers

import (
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	_ "go-programming-tour-book/blog-service/docs"
	"go-programming-tour-book/blog-service/global"
	"go-programming-tour-book/blog-service/internal/middleware"
	"go-programming-tour-book/blog-service/internal/routers/api"
	v1 "go-programming-tour-book/blog-service/internal/routers/api/v1"
	"go-programming-tour-book/blog-service/pkg/limiter"
	"net/http"
	"time"
)

var methodLimiters = limiter.NewMethodLimiter().AddBuckets(
	limiter.LimiterBucketRule{
		Key:          "/auth",
		FillInterval: time.Second,
		Capacity:     10,
		Quantum:      10,
	},
)

func NewRouter() *gin.Engine {
	r := gin.New()

	if global.ServerSetting.RunMode == "debug" {
		r.Use(gin.Logger(), gin.Recovery(), middleware.AppInfo())
	} else {
		r.Use(middleware.AccessLog())
		r.Use(middleware.Recovery())
	}

	//链路追踪中间件
	r.Use(middleware.Tracing())

	//限流器中间件
	r.Use(middleware.RateLimiter(methodLimiters))

	//上下文超时时间中间件
	r.Use(middleware.ContextTimeout(60 * time.Second))

	//验证器中间件
	r.Use(middleware.Translations())

	//定义swagger路由
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	//测试链接
	r.GET("/test", func(c *gin.Context) {
		write_timeout, _ := c.Get("write_timeout")

		c.JSON(200, gin.H{
			"write_timeout": write_timeout,
		})
	})

	apiv1 := r.Group("/api/v1")

	apiv1.Use(middleware.JWT())

	tag := v1.NewTag()

	article := v1.NewArticle()

	{
		apiv1.GET("/tags", tag.GetTag)
		apiv1.POST("/tags", tag.AddTag)
		apiv1.PUT("/tags/:id", tag.UpdateTag)
		apiv1.PATCH("/tags/:id/state", tag.UpdateTagState)
		apiv1.DELETE("/tags/:id", tag.DeleteTag)
	}

	{
		apiv1.GET("/articles", article.GetArticle)
		apiv1.POST("/articles", article.AddArticle)
		apiv1.PUT("/articles/:id", article.UpdateArticle)
		apiv1.PATCH("/articles/:id/state", article.UpdateArticleState)
		apiv1.DELETE("/articles/:id", article.DeleteArticle)
	}

	//上传文件接口
	upload := NewUpload()

	r.POST("/upload", upload.UploadFile)
	//静态资源
	r.StaticFS("/static", http.Dir(global.AppSetting.UploadSavePath))

	//获取jwt token
	auth := api.NewAuth()

	r.POST("/auth", auth.GetAuth)

	return r
}
